/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package FEMShapeFunctions;

import Integration.IFunction2D;
import MathLib.triangulation.SaveStructures.Node;

/**
 *
 * @author mark
 */
public class FEMShapeFunction2 implements IFunction2D{
    protected Node A;
    protected Node B;
    protected Node C;
    protected Node D;
    protected Node E;
    protected Node F;

    protected double S2;

    private int NodeNum;

    protected double ai ,
                     aj ,
                     ak ;
    protected double bi ,
                     bj ,
                     bk ;
    protected double ci ,
                     cj ,
                     ck ;

    public FEMShapeFunction2(Node A, Node B, Node C,Node D, Node E, Node F) {
            this.A = A;
            this.B = B;
            this.C = C;
            this.D = D;
            this.E = E;
            this.F = F;

            ai = C.x*E.y - E.x*C.y;
            aj = E.x*A.y - A.x*E.y;
            ak = A.x*C.y - C.x*A.y;

            bi = C.y-E.y;
            bj = E.y-A.y;
            bk = A.y-C.y;

            ci = E.x-C.x;
            cj = A.x-E.x;
            ck = C.x-A.x;

            double a =Math.sqrt( ( ck )*(ck) + (bk)*(bk) );   //a-b
            double b =Math.sqrt( (ci)*(ci) + (bi)*(bi) );
            double c =Math.sqrt( (cj)*(cj) + (bj)*(bj) );
            double p = (a+b+c)/2.0;
            S2 =  Math.sqrt( p*(p-a)*(p-b)*(p-c) )*2;
        }

        private double Li(double x, double y){
            return (ai+bi*x+ci*y)/S2;
        }

        private double Lj(double x, double y){
            return (aj+bj*x+cj*y)/S2;
        }

        private double Lk(double x, double y){
            return (aj+bj*x+cj*y)/S2;
        }

    public void setNodeNum(int NodeNum) {
        this.NodeNum = NodeNum;
        /**
         * 1 - вузол i;
         * 2 - вузол ij;
         * 3 - вузол j;
         * 4 - вузол jk;
         * 5 - вузол k;
         * 6 - вузол ki;
         */
    }

    public double calculate(double x, double y) {
        double l;
        switch(NodeNum){
            case 1: l=Li(x, y); return l*(2*l-1);
            case 2: return 4*Li(x, y)*Lj(x, y);
            case 3: l=Lj(x, y); return l*(2*l-1);
            case 4: return 4*Lj(x, y)*Lk(x, y);
            case 5: l=Lk(x, y); return l*(2*l-1);
            case 6: return 4*Lk(x, y)*Li(x, y);
            default: return 0.0;
        }
    }

    public double calculateDerivatyX(double x, double y) {
        switch(NodeNum){
            case 1: return bi*(4*Li(x, y)-1)/S2;
            case 2: return 4*(bj*Li(x, y)+bi*Lj(x, y))/S2;
            case 3: return bj*(4*Lj(x, y)-1)/S2;
            case 4: return 4*(bj*Lk(x, y)+bk*Lj(x, y))/S2;
            case 5: return bk*(4*Li(x, y)-1)/S2;
            case 6: return 4*(bk*Li(x, y)+bi*Lk(x, y))/S2;
            default: return 0.0;
        }
    }

    public double calculateDerivatyY(double x, double y) {
        switch(NodeNum){
            case 1: return ci*(4*Li(x, y)-1)/S2;
            case 2: return 4*(cj*Li(x, y)+ci*Lj(x, y))/S2;
            case 3: return cj*(4*Lj(x, y)-1)/S2;
            case 4: return 4*(cj*Lk(x, y)+ck*Lj(x, y))/S2;
            case 5: return ck*(4*Li(x, y)-1)/S2;
            case 6: return 4*(ck*Li(x, y)+ci*Lk(x, y))/S2;
            default: return 0.0;
        }
    }

    public double calculateI(double x, double y,int i) {
        double l;
        switch(i){
            case 1: l=Li(x, y); return l*(2*l-1);
            case 2: return 4*Li(x, y)*Lj(x, y);
            case 3: l=Lj(x, y); return l*(2*l-1);
            case 4: return 4*Lj(x, y)*Lk(x, y);
            case 5: l=Lk(x, y); return l*(2*l-1);
            case 6: return 4*Lk(x, y)*Li(x, y);
            default: return 0.0;
        }
    }

    public double calculateDerivatyXI(double x, double y,int i) {
        switch(i){
            case 1: return bi*(4*Li(x, y)-1)/S2;
            case 2: return 4*(bj*Li(x, y)+bi*Lj(x, y))/S2;
            case 3: return bj*(4*Lj(x, y)-1)/S2;
            case 4: return 4*(bj*Lk(x, y)+bk*Lj(x, y))/S2;
            case 5: return bk*(4*Li(x, y)-1)/S2;
            case 6: return 4*(bk*Li(x, y)+bi*Lk(x, y))/S2;
            default: return 0.0;
        }
    }

    public double calculateDerivatyYI(double x, double y,int i) {
        switch(i){
            case 1: return ci*(4*Li(x, y)-1)/S2;
            case 2: return 4*(cj*Li(x, y)+ci*Lj(x, y))/S2;
            case 3: return cj*(4*Lj(x, y)-1)/S2;
            case 4: return 4*(cj*Lk(x, y)+ck*Lj(x, y))/S2;
            case 5: return ck*(4*Li(x, y)-1)/S2;
            case 6: return 4*(ck*Li(x, y)+ci*Lk(x, y))/S2;
            default: return 0.0;
        }
    }

    public IFunction2D calculateMultFuncs(final int i,final int j){
        return new IFunction2D() {

            public double calculate(double x, double y) {
                return calculateI(x, y, i)*calculateI(x, y, j);
            }
           /**
            *
            *
            * @return the value func i multipled by derivatyX of func j
            */
            public double calculateDerivatyX(double x, double y) {
                return calculateI(x, y, i)*calculateDerivatyXI(x, y, j);
            }
            /**
            *
            *
            * @return the value func i multipled by derivatyY of func j
            */
            public double calculateDerivatyY(double x, double y) {
                return calculateI(x, y, i)*calculateDerivatyYI(x, y, j);
            }
        };
    }
}
